import base64
import io

import minio

from common import exception
from config import configuration


class SingleMinioClient:
    # Minio 客户端对象
    __minio_client = None

    def __new__(cls):
        if cls.__minio_client is None:
            cls._instance = super().__new__(cls)
            print("连接到Minio服务器{}".format(configuration.MINIO_ENDPOINT))
            cls.__minio_client = minio.Minio(
                endpoint=configuration.MINIO_ENDPOINT,
                access_key=configuration.MINIO_ACCESS_KEY,
                secret_key=configuration.MINIO_SECRET_KEY,
                secure=False
            )
        return cls.__minio_client


class MinioApiService:

    def __init__(self):
        self.__minio_client = SingleMinioClient()

    def upload_images(self, bucket_name, object_name, file_content):
        """
        图像上传
        :param bucket_name: bucket名称
        :param object_name: bucket中的对象名称
        :param file_content: base64编码后的文件
        """
        self.check_and_create_bucket(bucket_name)
        try:
            # 将 Base64 文件内容解码
            decoded_content = base64.b64decode(file_content)
            # 将解码后的内容转换为字节流
            file_data = io.BytesIO(decoded_content)
            self.__minio_client.put_object(
                bucket_name=bucket_name,
                object_name=object_name,
                data=file_data,
                length=len(decoded_content),
                content_type='image/png'
            )
        except Exception as err:
            raise exception.ServiceException(err)

    def upload_file(self, bucket_name, object_name, file_content):
        """
        文件上传
        :param bucket_name: bucket名称
        :param object_name: bucket中的对象名称
        :param file_content: base64编码后的文件
        """
        self.check_and_create_bucket(bucket_name)
        try:
            # 将 Base64 文件内容解码
            decoded_content = base64.b64decode(file_content)
            # 将解码后的内容转换为字节流
            file_data = io.BytesIO(decoded_content)
            self.__minio_client.put_object(
                bucket_name=bucket_name,
                object_name=object_name,
                data=file_data,
                length=len(decoded_content)
            )
        except Exception as err:
            raise exception.ServiceException(err)

    def download_file(self, bucket_name, object_name):
        """
        文件下载
        :param bucket_name: bucket名称
        :param object_name: bucket中的对象名称
        :return: base64编码后的文件
        """
        try:
            response = self.__minio_client.get_object(bucket_name, object_name)
            data = response.read()
            response.close()
            response.release_conn()
            encoded_data = base64.b64encode(data).decode('utf-8')
            return encoded_data
        except Exception as err:
            raise exception.ServiceException(err)

    def download_file_to_path(self, bucket_name, object_name, local_file_path):
        """
        文件下载到本地，不作为远程调用接口
        :param bucket_name: bucket名称
        :param object_name: bucket中的对象名称
        :param local_file_path:
        """
        self.__minio_client.fget_object(bucket_name, object_name, local_file_path)

    def check_and_create_bucket(self, bucket_name):
        """
        检查桶是否存在，不存在则创建出来
        :param bucket_name: 桶名
        """
        try:
            # 检查存储桶是否存在
            exists = self.__minio_client.bucket_exists(bucket_name)
            if exists:
                return
            else:
                # 创建存储桶
                self.__minio_client.make_bucket(bucket_name)
        except Exception as e:
            raise exception.ServiceException("储存桶检查失败！")
